//------------------------------------------------------------
//  Filename: heat_proc.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2016-10-10 16:52
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module HEAT_PROC ( 
    input clk_1khz,  
    input rst,  

    input  wire [15:0] heat_time, // in ms
    input  wire [7:0]  heat_speed,// max 100 ,not used now
    output reg         heat_status,
    input              heat_mode,
    input  wire        heat_key, 
    input  wire        heat_touch, 
    input  wire        heat_test,
    input  wire [15:0] vtmp_value,
    
    output reg         heat,
    output reg         heat_ledon
);   
//--------------------------------------------------------  
wire      clk = clk_1khz;

localparam COLD_CNT  = 200000;
localparam HIGH_TEMP = 'hFFFC;
localparam LOW_TEMP  = 'hFFF0;
localparam HEAT_STEP = 'h2000;   //8*1024 STEP 8.192s

reg[15:0] heat_cntr  ;
reg[31:0] cold_cntr  ;
reg[31:0] idle_cntr  ;
reg[31:0] speed_cntr ;
reg[31:0] heat_duty  ;
reg[15:0] led_flash_cntr;

wire      heat_time_out = (heat_cntr < heat_time)?1'b0:1'b1;
wire      cold_time_out = (cold_cntr < COLD_CNT)?1'b0:1'b1;  
//--------------------------------------------------------
reg[9:0] heat_sens_cntr1;
reg[9:0] heat_sens_cntr2;
//--------------------------------------------------------
parameter SENSER_PERIOD = 80;
//--------------------------------------------------------
reg heat_touch_ff;
always @(posedge clk) heat_touch_ff <= heat_touch;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
    	heat_sens_cntr1 <= SENSER_PERIOD;
    end
    else if(heat_touch_ff) begin
    	heat_sens_cntr1 <= (heat_sens_cntr1 < SENSER_PERIOD)?(heat_sens_cntr1 + 1):heat_sens_cntr1; 
    end
    else begin
        heat_sens_cntr1 <= 0;
    end
end
//--------------------------------------------------------
reg heat_key_ff;
always @(posedge clk) heat_key_ff <= ~heat_key;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
    	heat_sens_cntr2 <= 0;
    end 
    else if(heat_key_ff) begin
        heat_sens_cntr2 <= (heat_sens_cntr2 < SENSER_PERIOD)?(heat_sens_cntr2 + 1):heat_sens_cntr2; 
    end
    else begin
        heat_sens_cntr2 <= 0;
    end    
end 
//--------------------------------------------------------
reg heat_touch_sens;
reg heat_touch_sens_ff1;
reg heat_key_sens;
reg heat_key_sens_ff1;
always@(posedge clk) heat_touch_sens     <= (heat_sens_cntr1 == SENSER_PERIOD)?1'b1:1'b0; 
always@(posedge clk) heat_key_sens       <= (heat_sens_cntr2 == SENSER_PERIOD)?1'b1:1'b0; 
always@(posedge clk) heat_key_sens_ff1   <= heat_key_sens; 
always@(posedge clk) heat_touch_sens_ff1 <= heat_touch_sens; 
wire posedge_heat_key_sens   = heat_key_sens&(~heat_key_sens_ff1);
wire posedge_heat_touch_sens = heat_touch_sens&(~heat_touch_sens_ff1);
//--------------------------------------------------------  
localparam HEAT_IDLE  = 5'b00001;
localparam HEAT_MANUL = 5'b00010;
localparam HEAT_AUTO  = 5'b00100;
localparam HEAT_OFF   = 5'b01000;
localparam HEAT_COLD  = 5'b10000;
//--------------------------------------------------------
reg[4:0]  heat_state;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        heat_state <= HEAT_IDLE;        
    end 
    else begin 
        case(heat_state) 
            HEAT_IDLE: begin
                if(heat_test) begin
                    heat_state <= HEAT_MANUL;
                end
                else begin
                    if(heat_mode == 1) begin // auto mode
                        heat_state <= (posedge_heat_key_sens|posedge_heat_touch_sens)? HEAT_AUTO:HEAT_IDLE;  
                    end
                    else begin
                        heat_state <= (posedge_heat_key_sens)? HEAT_MANUL:HEAT_IDLE;  
                    end   
                end   
            end
            HEAT_MANUL: begin
                if(heat_time_out) begin
                    heat_state <= HEAT_OFF;
                end
                else begin
                    heat_state <= (posedge_heat_key_sens)? HEAT_OFF:HEAT_MANUL;
                end
            end
            HEAT_AUTO: begin
                if(heat_time_out) begin
                    heat_state <= HEAT_OFF;
                end
                else begin
                    heat_state <= (posedge_heat_key_sens)? HEAT_OFF:HEAT_AUTO;
                end                
            end
            HEAT_OFF: begin
                if(heat_test) begin
                    heat_state <= HEAT_COLD;
                end
                else begin
                    heat_state <= HEAT_IDLE;
                end
            end
            HEAT_COLD: begin
                heat_state <= (cold_time_out)?(HEAT_IDLE):(HEAT_COLD);
            end
            default:begin
                heat_state <= HEAT_IDLE;        
            end
        endcase    
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        speed_cntr  <= 32'b0;
    end 
    else if((heat_state == HEAT_IDLE)||(heat_state == HEAT_OFF))begin 
        speed_cntr  <= 32'b0;
    end 
    else begin  
        speed_cntr  <= (speed_cntr < HEAT_STEP)? (speed_cntr + 32'b1):0; //cntr for every step
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        heat_cntr  <= 16'b0;
    end 
    else if((heat_state == HEAT_IDLE)||(heat_state == HEAT_OFF))begin 
        heat_cntr  <= 16'b0;
    end 
    else if(heat_cntr < heat_time) begin
        heat_cntr  <= heat_cntr + 16'b1;
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        cold_cntr  <= 32'b0;
    end 
    else if(heat_state == HEAT_OFF)begin 
        cold_cntr  <= 32'b0;
    end 
    else if(cold_cntr < COLD_CNT) begin
        cold_cntr  <= cold_cntr + 32'b1;
    end
end
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        idle_cntr  <= (8*HEAT_STEP);
        heat_duty  <= 32'b0;
    end 
    else if(heat_state == HEAT_IDLE) begin  // max idle for 8*HEAT_DUTY s
        idle_cntr  <= (idle_cntr < (8*HEAT_STEP)) ? (idle_cntr + 32'b1):idle_cntr;  // more idle time .more heat duty
        heat_duty  <= {3'b0,idle_cntr[31:13],10'b0};                                // but no more than 8.192s
    end
    else begin
        idle_cntr  <= {11'b0,{heat_speed[7:0],3'b0},10'b0};  // init duty set as heat_speed
    end
end
//--------------------------------------------------------
reg heat_on;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        heat_status <= 1'b0;      
    end 
    else if((heat_state == HEAT_MANUL)||(heat_state == HEAT_AUTO)) begin 
        heat_status <= 1'b1;      
    end 
    else begin
        heat_status <= 1'b0;      
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        heat_on <= 1'b0;  
    end 
    else if(heat_status) begin 
    	// FUSION_V1
		//if(vtmp_value < LOW_TEMP) begin  
		//	heat_on <= (heat_duty > speed_cntr)? 1'b1:1'b0; // ontime = heat_duty/HEAT_STEP,most for 1
		//end 
		//else if(vtmp_value > HIGH_TEMP) begin
		//	heat_on <= 1'b0;
		//end 
		heat_on <= 1'b1;       
    end 
    else begin
        heat_on <= 1'b0;    
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        led_flash_cntr <= 16'b0;        
    end 
    else if(heat_state == HEAT_AUTO) begin 
        led_flash_cntr <= (led_flash_cntr < 1000)?(led_flash_cntr + 1):16'b0;        
    end 
    else begin
        led_flash_cntr <= 16'b0;        
    end
end 
//--------------------------------------------------------
reg heat_led;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        heat_led <= 1'b0;        
    end 
    else if(heat_state == HEAT_MANUL) begin 
        heat_led <= 1'b1;        
    end 
    else if(heat_state == HEAT_AUTO) begin
        heat_led <= (led_flash_cntr < 500)?1'b1:1'b0;        
    end
    else begin
        heat_led <= 1'b0;        
    end
end 
//--------------------------------------------------------
always @(posedge clk ) heat_ledon <= heat_led;
always @(posedge clk ) heat       <= ~heat_on;

endmodule
